/**
 * 客户端测试银行操作接口脚本
 * 专注于测试：HTTP登录、WebSocket选择角色、银行存取操作
 */

const http = require('http');
const WebSocket = require('ws');

// 测试配置
const CONFIG = {
    server: {
        host: 'localhost',
        port: 3000,
        protocol: 'http'
    },

    // 测试用户信息
    testUser: {
        mobile: '17091271111',
        password: '123456',
        passwordHash: 'e10adc3949ba59abbe56e057f20f883e' // 123456的SHA256
    },

    // 测试角色信息
    testCharacter: {
        name: '测试角色',
        sex: 1, // 1:男, 0:女
        roleType: 1, // 1:武士, 2:文人, 3:异师
        headIndex: 2
    }
};

class BankOperationsTester {
    constructor() {
        this.token = null;
        this.userId = null;
        this.ws = null;
        this.characters = [];
        this.selectedCharacter = null;
        this.testResults = [];
        this.bankData = null;
        this.currentTest = null;
        this.testTimeout = null;
    }

    // 运行完整测试流程
    async runTest() {
        console.log('🚀 开始客户端银行操作接口测试...\n');
        console.log('测试目标：HTTP登录 → WebSocket连接 → 选择角色 → 测试银行存取操作\n');

        try {
            // 1. HTTP登录
            await this.testHttpLogin();

            // 2. 建立WebSocket连接
            await this.testWebSocketConnection();

            // 3. 查询角色列表
            await this.testQueryCharacters();

            // 4. 如果没有角色，先创建角色
            if (this.characters.length === 0) {
                // await this.testCreateCharacter();
                // 重新查询角色列表
                await this.testQueryCharacters();
            }

            // 5. 选择角色
            await this.testSelectCharacter();

            // 6. 测试1450接口 - 查询钱庄信息
            await this.testCode1450();

            // 7. 测试1457接口 - 银币从银行取出
            await this.testCode1457();

            // 8. 测试1459接口 - 银币存入银行
            await this.testCode1459();

            // 9. 测试1460接口 - 金币从银行取出
            await this.testCode1460();

            // 10. 测试1462接口 - 金币存入银行
            await this.testCode1462();

            // 11. 再次查询钱庄信息，验证操作结果
            await this.testCode1450Again();

            // 12. 断开连接
            await this.testDisconnect();

            // 输出测试结果
            this.printTestResults();

        } catch (error) {
            console.error('❌ 测试过程中发生错误:', error.message);
            this.addTestResult('整体测试', false, error.message);
        }
    }

    // 1. HTTP登录测试
    async testHttpLogin() {
        console.log('🔐 步骤1: HTTP登录测试...');

        try {
            // 首先尝试注册用户（如果不存在）
            await this.registerUser();

            // 执行登录
            const loginData = await this.makeHttpRequest('/user-service/user/login', 'POST', {
                mobile: CONFIG.testUser.mobile,
                pwd: CONFIG.testUser.passwordHash
            });

            if (loginData.code === 0 && loginData.data) {
                this.userId = loginData.data.userId;
                this.token = loginData.data.accessToken;

                console.log(`✅ 登录成功: userId=${this.userId}, token=${this.token.substring(0, 8)}...`);
                this.addTestResult('HTTP登录', true, `用户ID: ${this.userId}`);
            } else {
                throw new Error(`登录失败: ${loginData.msg || '未知错误'}`);
            }

        } catch (error) {
            console.log('❌ 登录失败:', error.message);
            this.addTestResult('HTTP登录', false, error.message);
            throw error;
        }
    }

    // 注册用户（如果不存在）
    async registerUser() {
        try {
            const res = await this.makeHttpRequest('/user-service/user/register', 'POST', {
                mobile: CONFIG.testUser.mobile,
                pwd: CONFIG.testUser.passwordHash,
                captcha: '123456' // 模拟验证码
            });
            console.log('📝 用户注册成功', res);
        } catch (error) {
            // 如果用户已存在，忽略错误
            if (error.message.includes('MOBILE_EXISTS') || error.message.includes('已存在')) {
                console.log('👤 用户已存在，跳过注册');
            } else {
                console.log('⚠️ 注册失败:', error.message);
            }
        }
    }

    // 2. WebSocket连接测试
    async testWebSocketConnection() {
        console.log('\n🔌 步骤2: WebSocket连接测试...');

        return new Promise((resolve, reject) => {
            try {
                const wsUrl = `ws://${CONFIG.server.host}:${CONFIG.server.port}/user-service/websocket?t=${this.token}`;
                this.ws = new WebSocket(wsUrl);

                this.ws.on('open', async () => {
                    console.log('✅ WebSocket连接成功');
                    this.addTestResult('WebSocket连接', true, '连接建立成功');

                    // 设置消息监听器
                    this.setupMessageHandler();

                    // 等待连接完全稳定
                    await this.delay(500);
                    resolve();
                });

                this.ws.on('error', (error) => {
                    console.log('❌ WebSocket连接失败:', error.message);
                    this.addTestResult('WebSocket连接', false, error.message);
                    reject(error);
                });

                this.ws.on('close', () => {
                    console.log('🔌 WebSocket连接已关闭');
                });

                // 连接超时
                setTimeout(() => {
                    if (this.ws.readyState === WebSocket.CONNECTING) {
                        this.ws.close();
                        reject(new Error('连接超时'));
                    }
                }, 10000);

            } catch (error) {
                reject(error);
            }
        });
    }

    // 设置消息处理器
    setupMessageHandler() {
        this.ws.on('message', (data) => {
            try {
                const message = JSON.parse(data.toString());
                console.log('📨 收到消息:', JSON.stringify(message, null, 2));

                // 根据act_id处理不同类型的响应
                this.handleWebSocketResponse(message);

            } catch (error) {
                console.error('❌ 消息解析失败:', error.message);
            }
        });
    }

    // 处理WebSocket响应
    handleWebSocketResponse(message) {
        const { act_id, code, roleList, roleCount, data, msg } = message;

        switch (act_id) {
            case 3: // 查询角色列表响应
                if (roleList) {
                    this.characters = roleList;
                    console.log(`✅ 查询角色列表成功，共 ${roleCount} 个角色`);
                }
                break;

            case 4: // 创建角色响应
                if (code === 0) {
                    console.log('✅ 创建角色成功');
                }
                break;

            case 5: // 选择角色响应
                if (code === 0) {
                    console.log('✅ 选择角色成功');
                }
                break;

            case 1450: // 钱庄信息查询响应
                if (code === 0 && data) {
                    this.bankData = data;
                    const { balanceGold, balanceMoney, gold, money } = data;
                    console.log(`✅ 钱庄信息查询成功: 钱庄金币=${balanceGold}, 钱庄银两=${balanceMoney}, 普通金币=${gold}, 普通银两=${money}`);
                }
                break;

            case 1457: // 银币取出响应
                if (this.currentTest && this.currentTest.act_id === 1457) {
                    this.currentTest.resolve(message);
                }
                break;

            case 1459: // 银币存入响应
                if (this.currentTest && this.currentTest.act_id === 1459) {
                    this.currentTest.resolve(message);
                }
                break;

            case 1460: // 金币取出响应
                if (this.currentTest && this.currentTest.act_id === 1460) {
                    this.currentTest.resolve(message);
                }
                break;

            case 1462: // 金币存入响应
                if (this.currentTest && this.currentTest.act_id === 1462) {
                    this.currentTest.resolve(message);
                }
                break;

            default:
                console.log(`📨 收到未处理的消息: act_id=${act_id}`);
        }
    }

    // 3. 查询角色列表测试
    async testQueryCharacters() {
        console.log('\n👥 步骤3: 查询角色列表...');

        try {
            await this.sendWebSocketMessage(3, {});
            await this.delay(1000); // 等待响应

            if (this.characters.length > 0) {
                console.log(`✅ 查询角色列表成功，共 ${this.characters.length} 个角色`);
                this.addTestResult('查询角色列表', true, `共 ${this.characters.length} 个角色`);
            } else {
                console.log('⚠️ 角色列表为空，需要创建角色');
                this.addTestResult('查询角色列表', true, '角色列表为空');
            }

        } catch (error) {
            console.log('❌ 查询角色列表失败:', error.message);
            this.addTestResult('查询角色列表', false, error.message);
            throw error;
        }
    }

    // 4. 创建角色测试
    async testCreateCharacter() {
        console.log('\n👤 步骤4: 创建测试角色...');

        try {
            await this.sendWebSocketMessage(4, CONFIG.testCharacter);
            await this.delay(1000); // 等待响应

            console.log('✅ 创建角色请求已发送');
            this.addTestResult('创建角色', true, '角色创建请求已发送');

        } catch (error) {
            console.log('❌ 创建角色失败:', error.message);
            this.addTestResult('创建角色', false, error.message);
            throw error;
        }
    }

    // 5. 选择角色测试
    async testSelectCharacter() {
        console.log('\n🎯 步骤5: 选择角色...');

        try {
            if (this.characters.length > 0) {
                this.selectedCharacter = this.characters[0];
                await this.sendWebSocketMessage(5, {
                    characterId: this.selectedCharacter.id,
                    roleId: this.selectedCharacter.id,
                    userId: this.selectedCharacter.id,
                    roleName: this.selectedCharacter.name
                });
                await this.delay(1000); // 等待响应

                console.log(`✅ 选择角色成功: ${this.selectedCharacter.name}`);
                this.addTestResult('选择角色', true, `角色: ${this.selectedCharacter.name}`);
            } else {
                throw new Error('没有可选择的角色');
            }

        } catch (error) {
            console.log('❌ 选择角色失败:', error.message);
            this.addTestResult('选择角色', false, error.message);
            throw error;
        }
    }

    // 6. 测试1450接口 - 钱庄信息查询
    async testCode1450() {
        console.log('\n🏦 步骤6: 测试1450接口 (钱庄信息查询)...');

        try {
            await this.sendWebSocketMessage(1450, { pageNum: 0 });
            await this.delay(1000); // 等待响应

            if (this.bankData) {
                const { balanceGold, balanceMoney, gold, money } = this.bankData;
                if (!isNaN(balanceGold) && !isNaN(balanceMoney) && !isNaN(gold) && !isNaN(money)) {
                    console.log(`✅ 钱庄信息查询成功: 钱庄金币=${balanceGold}, 钱庄银两=${balanceMoney}, 普通金币=${gold}, 普通银两=${money}`);
                    this.addTestResult('1450接口测试', true, `钱庄金币: ${balanceGold}, 钱庄银两: ${balanceMoney}, 普通金币: ${gold}, 普通银两: ${money}`);
                } else {
                    this.addTestResult('1450接口测试', false, '数据类型错误');
                }
            } else {
                this.addTestResult('1450接口测试', false, '缺少必要字段');
            }

        } catch (error) {
            console.log(`❌ 1450接口调用失败: ${error.message}`);
            this.addTestResult('1450接口测试', false, error.message);
        }
    }

    // 7. 测试1457接口 - 银币从银行取出
    async testCode1457() {
        console.log('\n🏦 步骤7: 测试1457接口 (银币从银行取出)...');

        try {
            // 测试1: 正常取出
            const result1 = await this.sendWebSocketMessageWithResponse(1457, { num: 100, pwd: '123456' });

            if (result1.code === 0) {
                this.addTestResult('1457接口测试-正常取出', true, '银币取出成功');
            } else {
                this.addTestResult('1457接口测试-正常取出', false, `取出失败: ${result1.msg}`);
            }

            // 测试2: 金额为0
            const result2 = await this.sendWebSocketMessageWithResponse(1457, { num: 0, pwd: '123456' });

            if (result2.code === 8) {
                this.addTestResult('1457接口测试-金额为0', true, '正确返回错误码8');
            } else {
                this.addTestResult('1457接口测试-金额为0', false, `期望错误码8，实际: ${result2.code}`);
            }

            // 测试3: 密码错误
            const result3 = await this.sendWebSocketMessageWithResponse(1457, { num: 100, pwd: 'wrong' });

            if (result3.code === -1) {
                this.addTestResult('1457接口测试-密码错误', true, '正确返回错误码-1');
            } else {
                this.addTestResult('1457接口测试-密码错误', false, `期望错误码-1，实际: ${result3.code}`);
            }

        } catch (error) {
            this.addTestResult('1457接口测试', false, `测试异常: ${error.message}`);
        }
    }

    // 8. 测试1459接口 - 银币存入银行
    async testCode1459() {
        console.log('\n🏦 步骤8: 测试1459接口 (银币存入银行)...');

        try {
            // 测试1: 正常存入
            const result1 = await this.sendWebSocketMessageWithResponse(1459, { num: 100 });

            if (result1.code === 0) {
                this.addTestResult('1459接口测试-正常存入', true, '银币存入成功');
            } else {
                this.addTestResult('1459接口测试-正常存入', false, `存入失败: ${result1.msg}`);
            }

            // 测试2: 金额为0
            const result2 = await this.sendWebSocketMessageWithResponse(1459, { num: 0 });

            if (result2.code === 8) {
                this.addTestResult('1459接口测试-金额为0', true, '正确返回错误码8');
            } else {
                this.addTestResult('1459接口测试-金额为0', false, `期望错误码8，实际: ${result2.code}`);
            }

        } catch (error) {
            this.addTestResult('1459接口测试', false, `测试异常: ${error.message}`);
        }
    }

    // 9. 测试1460接口 - 金币从银行取出
    async testCode1460() {
        console.log('\n🏦 步骤9: 测试1460接口 (金币从银行取出)...');

        try {
            // 测试1: 正常取出
            const result1 = await this.sendWebSocketMessageWithResponse(1460, { num: 100, pwd: '123456' });

            if (result1.code === 0) {
                this.addTestResult('1460接口测试-正常取出', true, '金币取出成功');
            } else {
                this.addTestResult('1460接口测试-正常取出', false, `取出失败: ${result1.msg}`);
            }

            // 测试2: 金额为0
            const result2 = await this.sendWebSocketMessageWithResponse(1460, { num: 0, pwd: '123456' });

            if (result2.code === 8) {
                this.addTestResult('1460接口测试-金额为0', true, '正确返回错误码8');
            } else {
                this.addTestResult('1460接口测试-金额为0', false, `期望错误码8，实际: ${result2.code}`);
            }

            // 测试3: 密码错误
            const result3 = await this.sendWebSocketMessageWithResponse(1460, { num: 100, pwd: 'wrong' });

            if (result3.code === -1) {
                this.addTestResult('1460接口测试-密码错误', true, '正确返回错误码-1');
            } else {
                this.addTestResult('1460接口测试-密码错误', false, `期望错误码-1，实际: ${result3.code}`);
            }

        } catch (error) {
            this.addTestResult('1460接口测试', false, `测试异常: ${error.message}`);
        }
    }

    // 10. 测试1462接口 - 金币存入银行
    async testCode1462() {
        console.log('\n🏦 步骤10: 测试1462接口 (金币存入银行)...');

        try {
            // 测试1: 正常存入
            const result1 = await this.sendWebSocketMessageWithResponse(1462, { num: 100 });

            if (result1.code === 0) {
                this.addTestResult('1462接口测试-正常存入', true, '金币存入成功');
            } else {
                this.addTestResult('1462接口测试-正常存入', false, `存入失败: ${result1.msg}`);
            }

            // 测试2: 金额为0
            const result2 = await this.sendWebSocketMessageWithResponse(1462, { num: 0 });

            if (result2.code === 8) {
                this.addTestResult('1462接口测试-金额为0', true, '正确返回错误码8');
            } else {
                this.addTestResult('1462接口测试-金额为0', false, `期望错误码8，实际: ${result2.code}`);
            }

        } catch (error) {
            this.addTestResult('1462接口测试', false, `测试异常: ${error.message}`);
        }
    }

    // 11. 再次查询钱庄信息，验证操作结果
    async testCode1450Again() {
        console.log('\n🏦 步骤11: 再次查询钱庄信息，验证操作结果...');

        try {
            await this.sendWebSocketMessage(1450, { pageNum: 0 });
            await this.delay(1000); // 等待响应

            if (this.bankData) {
                const { balanceGold, balanceMoney, gold, money } = this.bankData;
                console.log(`✅ 钱庄信息查询成功: 钱庄金币=${balanceGold}, 钱庄银两=${balanceMoney}, 普通金币=${gold}, 普通银两=${money}`);
                this.addTestResult('钱庄信息验证', true, `最终余额 - 钱庄金币: ${balanceGold}, 钱庄银两: ${balanceMoney}, 普通金币: ${gold}, 普通银两: ${money}`);
            } else {
                this.addTestResult('钱庄信息验证', false, '无法获取最终余额信息');
            }

        } catch (error) {
            console.log(`❌ 钱庄信息验证失败: ${error.message}`);
            this.addTestResult('钱庄信息验证', false, error.message);
        }
    }

    // 发送WebSocket消息并等待响应
    async sendWebSocketMessageWithResponse(actId, data) {
        return new Promise((resolve, reject) => {
            this.currentTest = { act_id: actId, resolve, reject };

            // 设置超时
            this.testTimeout = setTimeout(() => {
                if (this.currentTest && this.currentTest.act_id === actId) {
                    this.currentTest.reject(new Error('请求超时'));
                    this.currentTest = null;
                }
            }, 10000);

            // 发送消息
            this.sendWebSocketMessage(actId, data);
        });
    }

    // 发送WebSocket消息
    sendWebSocketMessage(actId, data) {
        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
            const message = { c: actId, d: data };
            console.log(`📤 发送消息: ${JSON.stringify(message)}`);
            this.ws.send(JSON.stringify(message));
        } else {
            throw new Error('WebSocket连接未建立或已关闭');
        }
    }

    // 12. 断开连接
    async testDisconnect() {
        console.log('\n🔌 步骤12: 断开WebSocket连接...');
        if (this.ws) {
            this.ws.close();
            console.log('✅ WebSocket连接已断开');
        }
    }

    // 添加测试结果
    addTestResult(test, success, message) {
        this.testResults.push({ test, success, message });
        const status = success ? '✅' : '❌';
        console.log(`${status} ${test}: ${message}`);
    }

    // 打印测试结果
    printTestResults() {
        console.log('\n📊 测试结果汇总:');
        console.log('='.repeat(50));

        let successCount = 0;
        let totalCount = this.testResults.length;

        this.testResults.forEach((result, index) => {
            const status = result.success ? '✅' : '❌';
            console.log(`${index + 1}. ${status} ${result.test}: ${result.message}`);
            if (result.success) successCount++;
        });

        console.log('='.repeat(50));
        console.log(`总计: ${successCount}/${totalCount} 项测试通过`);

        if (successCount === totalCount) {
            console.log('🎉 所有测试通过！');
        } else {
            console.log('⚠️  部分测试失败，请检查日志');
        }
    }

    // HTTP请求工具方法
    async makeHttpRequest(path, method = 'GET', data = null) {
        return new Promise((resolve, reject) => {
            const options = {
                hostname: CONFIG.server.host,
                port: CONFIG.server.port,
                path: path,
                method: method,
                headers: {
                    'Content-Type': 'application/json',
                }
            };

            if (data) {
                const postData = JSON.stringify(data);
                options.headers['Content-Length'] = Buffer.byteLength(postData);
            }

            const req = http.request(options, (res) => {
                let body = '';

                res.on('data', (chunk) => {
                    body += chunk;
                });

                res.on('end', () => {
                    try {
                        const responseData = JSON.parse(body);
                        if (res.statusCode >= 200 && res.statusCode < 300) {
                            resolve(responseData);
                        } else {
                            reject(new Error(`HTTP ${res.statusCode}: ${responseData.message || body}`));
                        }
                    } catch (error) {
                        if (res.statusCode >= 200 && res.statusCode < 300) {
                            resolve(body);
                        } else {
                            reject(new Error(`HTTP ${res.statusCode}: ${body}`));
                        }
                    }
                });
            });

            req.on('error', (error) => {
                reject(error);
            });

            if (data) {
                req.write(JSON.stringify(data));
            }

            req.end();
        });
    }

    // 延迟函数
    async delay(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
}

// 运行测试
async function main() {
    const tester = new BankOperationsTester();
    await tester.runTest();
}

// 如果直接运行此脚本
if (require.main === module) {
    main().catch((error) => {
        console.error('💥 测试脚本执行失败:', error.message);
        process.exit(1);
    });
}

module.exports = BankOperationsTester;
